/**
 * EasyUI for jQuery 1.5.5.4
 *
 * Copyright (c) 2009-2018 www.jeasyui.com. All rights reserved.
 *
 * Licensed under the freeware license: http://www.jeasyui.com/license_freeware.php
 * To use it on other terms please contact us: info@jeasyui.com
 *
 */
/**
 * propertygrid - EasyUI for jQuery
 *
 * Dependencies:
 *     datagrid
 *
 */
(function ($) {
    var currTarget;
    $(document).unbind('.propertygrid').bind('mousedown.propertygrid', function (e) {
        var p = $(e.target).closest('div.datagrid-view,div.combo-panel');
        if (p.length) {
            return;
        }
        stopEditing(currTarget);
        currTarget = undefined;
    });

    function buildGrid(target) {
        var state = $.data(target, 'propertygrid');
        var opts = $.data(target, 'propertygrid').options;
        $(target).datagrid($.extend({}, opts, {
            cls: 'propertygrid',
            view: (opts.showGroup ? opts.groupView : opts.view),
            onBeforeEdit: function (index, row) {
                if (opts.onBeforeEdit.call(target, index, row) == false) {
                    return false;
                }
                var dg = $(this);
                var row = dg.datagrid('getRows')[index];
                var col = dg.datagrid('getColumnOption', 'value');
                col.editor = row.editor;
            },
            onClickCell: function (index, field, value) {
                if (currTarget != this) {
                    stopEditing(currTarget);
                    currTarget = this;
                }
                if (opts.editIndex != index) {
                    stopEditing(currTarget);
                    $(this).datagrid('beginEdit', index);
                    var ed = $(this).datagrid('getEditor', {index: index, field: field});
                    if (!ed) {
                        ed = $(this).datagrid('getEditor', {index: index, field: 'value'});
                    }
                    if (ed) {
                        var t = $(ed.target);
                        var input = t.data('textbox') ? t.textbox('textbox') : t;
                        input.focus();
                        opts.editIndex = index;
                    }
                }
                opts.onClickCell.call(target, index, field, value);
            },
            loadFilter: function (data) {
                stopEditing(this);
                return opts.loadFilter.call(this, data);
            }
        }));
    }

    function stopEditing(target) {
        var t = $(target);
        if (!t.length) {
            return
        }
        var opts = $.data(target, 'propertygrid').options;
        opts.finder.getTr(target, null, 'editing').each(function () {
            var index = parseInt($(this).attr('datagrid-row-index'));
            if (t.datagrid('validateRow', index)) {
                t.datagrid('endEdit', index);
            } else {
                t.datagrid('cancelEdit', index);
            }
        });
        opts.editIndex = undefined;
    }

    $.fn.propertygrid = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.propertygrid.methods[options];
            if (method) {
                return method(this, param);
            } else {
                return this.datagrid(options, param);
            }
        }

        options = options || {};
        return this.each(function () {
            var state = $.data(this, 'propertygrid');
            if (state) {
                $.extend(state.options, options);
            } else {
                var opts = $.extend({}, $.fn.propertygrid.defaults, $.fn.propertygrid.parseOptions(this), options);
                opts.frozenColumns = $.extend(true, [], opts.frozenColumns);
                opts.columns = $.extend(true, [], opts.columns);
                $.data(this, 'propertygrid', {
                    options: opts
                });
            }
            buildGrid(this);
        });
    }

    $.fn.propertygrid.methods = {
        options: function (jq) {
            return $.data(jq[0], 'propertygrid').options;
        }
    };

    $.fn.propertygrid.parseOptions = function (target) {
        return $.extend({}, $.fn.datagrid.parseOptions(target), $.parser.parseOptions(target, [{showGroup: 'boolean'}]));
    };

    // the group view definition
    var groupview = $.extend({}, $.fn.datagrid.defaults.view, {
        render: function (target, container, frozen) {
            var table = [];
            var groups = this.groups;
            for (var i = 0; i < groups.length; i++) {
                table.push(this.renderGroup.call(this, target, i, groups[i], frozen));
            }
            $(container).html(table.join(''));
        },

        renderGroup: function (target, groupIndex, group, frozen) {
            var state = $.data(target, 'datagrid');
            var opts = state.options;
            var fields = $(target).datagrid('getColumnFields', frozen);
            var hasFrozen = opts.frozenColumns && opts.frozenColumns.length;

            if (frozen) {
                if (!(opts.rownumbers || hasFrozen)) {
                    return '';
                }
            }

            var table = [];

            var css = opts.groupStyler.call(target, group.value, group.rows);
            var cs = parseCss(css, 'datagrid-group');
            table.push('<div group-index=' + groupIndex + ' ' + cs + '>');
            if ((frozen && (opts.rownumbers || opts.frozenColumns.length)) ||
                (!frozen && !(opts.rownumbers || opts.frozenColumns.length))) {
                table.push('<span class="datagrid-group-expander">');
                table.push('<span class="datagrid-row-expander datagrid-row-collapse">&nbsp;</span>');
                table.push('</span>');
            }
            if ((frozen && hasFrozen) || (!frozen)) {
                table.push('<span class="datagrid-group-title">');
                table.push(opts.groupFormatter.call(target, group.value, group.rows));
                table.push('</span>');
            }
            table.push('</div>');

            table.push('<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0"><tbody>');
            var index = group.startIndex;
            for (var j = 0; j < group.rows.length; j++) {
                var css = opts.rowStyler ? opts.rowStyler.call(target, index, group.rows[j]) : '';
                var classValue = '';
                var styleValue = '';
                if (typeof css == 'string') {
                    styleValue = css;
                } else if (css) {
                    classValue = css['class'] || '';
                    styleValue = css['style'] || '';
                }

                var cls = 'class="datagrid-row ' + (index % 2 && opts.striped ? 'datagrid-row-alt ' : ' ') + classValue + '"';
                var style = styleValue ? 'style="' + styleValue + '"' : '';
                var rowId = state.rowIdPrefix + '-' + (frozen ? 1 : 2) + '-' + index;
                table.push('<tr id="' + rowId + '" datagrid-row-index="' + index + '" ' + cls + ' ' + style + '>');
                table.push(this.renderRow.call(this, target, fields, frozen, index, group.rows[j]));
                table.push('</tr>');
                index++;
            }
            table.push('</tbody></table>');
            return table.join('');

            function parseCss(css, cls) {
                var classValue = '';
                var styleValue = '';
                if (typeof css == 'string') {
                    styleValue = css;
                } else if (css) {
                    classValue = css['class'] || '';
                    styleValue = css['style'] || '';
                }
                return 'class="' + cls + (classValue ? ' ' + classValue : '') + '" ' +
                    'style="' + styleValue + '"';
            }
        },

        bindEvents: function (target) {
            var state = $.data(target, 'datagrid');
            var dc = state.dc;
            var body = dc.body1.add(dc.body2);
            var clickHandler = ($.data(body[0], 'events') || $._data(body[0], 'events')).click[0].handler;
            body.unbind('click').bind('click', function (e) {
                var tt = $(e.target);
                var expander = tt.closest('span.datagrid-row-expander');
                if (expander.length) {
                    var gindex = expander.closest('div.datagrid-group').attr('group-index');
                    if (expander.hasClass('datagrid-row-collapse')) {
                        $(target).datagrid('collapseGroup', gindex);
                    } else {
                        $(target).datagrid('expandGroup', gindex);
                    }
                } else {
                    clickHandler(e);
                }
                e.stopPropagation();
            });
        },

        onBeforeRender: function (target, rows) {
            var state = $.data(target, 'datagrid');
            var opts = state.options;

            initCss();

            var groups = [];
            for (var i = 0; i < rows.length; i++) {
                var row = rows[i];
                var group = getGroup(row[opts.groupField]);
                if (!group) {
                    group = {
                        value: row[opts.groupField],
                        rows: [row]
                    };
                    groups.push(group);
                } else {
                    group.rows.push(row);
                }
            }

            var index = 0;
            var newRows = [];
            for (var i = 0; i < groups.length; i++) {
                var group = groups[i];
                group.startIndex = index;
                index += group.rows.length;
                newRows = newRows.concat(group.rows);
            }

            state.data.rows = newRows;
            this.groups = groups;

            var that = this;
            setTimeout(function () {
                that.bindEvents(target);
            }, 0);

            function getGroup(value) {
                for (var i = 0; i < groups.length; i++) {
                    var group = groups[i];
                    if (group.value == value) {
                        return group;
                    }
                }
                return null;
            }

            function initCss() {
                if (!$('#datagrid-group-style').length) {
                    $('head').append(
                        '<style id="datagrid-group-style">' +
                        '.datagrid-group{height:' + opts.groupHeight + 'px;overflow:hidden;font-weight:bold;border-bottom:1px solid #ccc;white-space:nowrap;word-break:normal;}' +
                        '.datagrid-group-title,.datagrid-group-expander{display:inline-block;vertical-align:bottom;height:100%;line-height:' + opts.groupHeight + 'px;padding:0 4px;}' +
                        '.datagrid-group-title{position:relative;}' +
                        '.datagrid-group-expander{width:' + opts.expanderWidth + 'px;text-align:center;padding:0}' +
                        '.datagrid-row-expander{margin:' + Math.floor((opts.groupHeight - 16) / 2) + 'px 0;display:inline-block;width:16px;height:16px;cursor:pointer}' +
                        '</style>'
                    );
                }
            }
        },
        onAfterRender: function (target) {
            $.fn.datagrid.defaults.view.onAfterRender.call(this, target);

            var view = this;
            var state = $.data(target, 'datagrid');
            var opts = state.options;
            if (!state.onResizeColumn) {
                state.onResizeColumn = opts.onResizeColumn;
            }
            if (!state.onResize) {
                state.onResize = opts.onResize;
            }
            opts.onResizeColumn = function (field, width) {
                view.resizeGroup(target);
                state.onResizeColumn.call(target, field, width);
            }
            opts.onResize = function (width, height) {
                view.resizeGroup(target);
                state.onResize.call($(target).datagrid('getPanel')[0], width, height);
            }
            view.resizeGroup(target);
        }
    });

    $.extend($.fn.datagrid.methods, {
        groups: function (jq) {
            return jq.datagrid('options').view.groups;
        },
        expandGroup: function (jq, groupIndex) {
            return jq.each(function () {
                var opts = $(this).datagrid('options');
                var view = $.data(this, 'datagrid').dc.view;
                var group = view.find(groupIndex != undefined ? 'div.datagrid-group[group-index="' + groupIndex + '"]' : 'div.datagrid-group');
                var expander = group.find('span.datagrid-row-expander');
                if (expander.hasClass('datagrid-row-expand')) {
                    expander.removeClass('datagrid-row-expand').addClass('datagrid-row-collapse');
                    group.next('table').show();
                }
                $(this).datagrid('fixRowHeight');
                if (opts.onExpandGroup) {
                    opts.onExpandGroup.call(this, groupIndex);
                }
            });
        },
        collapseGroup: function (jq, groupIndex) {
            return jq.each(function () {
                var opts = $(this).datagrid('options');
                var view = $.data(this, 'datagrid').dc.view;
                var group = view.find(groupIndex != undefined ? 'div.datagrid-group[group-index="' + groupIndex + '"]' : 'div.datagrid-group');
                var expander = group.find('span.datagrid-row-expander');
                if (expander.hasClass('datagrid-row-collapse')) {
                    expander.removeClass('datagrid-row-collapse').addClass('datagrid-row-expand');
                    group.next('table').hide();
                }
                $(this).datagrid('fixRowHeight');
                if (opts.onCollapseGroup) {
                    opts.onCollapseGroup.call(this, groupIndex);
                }
            });
        },
        scrollToGroup: function (jq, groupIndex) {
            return jq.each(function () {
                var state = $.data(this, 'datagrid');
                var dc = state.dc;
                var grow = dc.body2.children('div.datagrid-group[group-index="' + groupIndex + '"]');
                if (grow.length) {
                    var groupHeight = grow.outerHeight();
                    var headerHeight = dc.view2.children('div.datagrid-header')._outerHeight();
                    var frozenHeight = dc.body2.outerHeight(true) - dc.body2.outerHeight();
                    var top = grow.position().top - headerHeight - frozenHeight;
                    if (top < 0) {
                        dc.body2.scrollTop(dc.body2.scrollTop() + top);
                    } else if (top + groupHeight > dc.body2.height() - 18) {
                        dc.body2.scrollTop(dc.body2.scrollTop() + top + groupHeight - dc.body2.height() + 18);
                    }
                }
            });
        }
    });

    $.extend(groupview, {
        refreshGroupTitle: function (target, groupIndex) {
            var state = $.data(target, 'datagrid');
            var opts = state.options;
            var dc = state.dc;
            var group = this.groups[groupIndex];
            var span = dc.body1.add(dc.body2).children('div.datagrid-group[group-index=' + groupIndex + ']').find('span.datagrid-group-title');
            span.html(opts.groupFormatter.call(target, group.value, group.rows));
        },
        resizeGroup: function (target, groupIndex) {
            var state = $.data(target, 'datagrid');
            var dc = state.dc;
            var ht = dc.header2.find('table');
            var fr = ht.find('tr.datagrid-filter-row').hide();
            var ww = ht.width();
            if (groupIndex == undefined) {
                var groupHeader = dc.body2.children('div.datagrid-group');
            } else {
                var groupHeader = dc.body2.children('div.datagrid-group[group-index=' + groupIndex + ']');
            }
            groupHeader._outerWidth(ww);
            var opts = state.options;
            if (opts.frozenColumns && opts.frozenColumns.length) {
                var width = dc.view1.width() - opts.expanderWidth;
                var isRtl = dc.view1.css('direction').toLowerCase() == 'rtl';
                groupHeader.find('.datagrid-group-title').css(isRtl ? 'right' : 'left', -width + 'px');
            }
            if (fr.length) {
                if (opts.showFilterBar) {
                    fr.show();
                }
            }
            // fr.show();
        },

        insertRow: function (target, index, row) {
            var state = $.data(target, 'datagrid');
            var opts = state.options;
            var dc = state.dc;
            var group = null;
            var groupIndex;

            if (!state.data.rows.length) {
                $(target).datagrid('loadData', [row]);
                return;
            }

            for (var i = 0; i < this.groups.length; i++) {
                if (this.groups[i].value == row[opts.groupField]) {
                    group = this.groups[i];
                    groupIndex = i;
                    break;
                }
            }
            if (group) {
                if (index == undefined || index == null) {
                    index = state.data.rows.length;
                }
                if (index < group.startIndex) {
                    index = group.startIndex;
                } else if (index > group.startIndex + group.rows.length) {
                    index = group.startIndex + group.rows.length;
                }
                $.fn.datagrid.defaults.view.insertRow.call(this, target, index, row);

                if (index >= group.startIndex + group.rows.length) {
                    _moveTr(index, true);
                    _moveTr(index, false);
                }
                group.rows.splice(index - group.startIndex, 0, row);
            } else {
                group = {
                    value: row[opts.groupField],
                    rows: [row],
                    startIndex: state.data.rows.length
                }
                groupIndex = this.groups.length;
                dc.body1.append(this.renderGroup.call(this, target, groupIndex, group, true));
                dc.body2.append(this.renderGroup.call(this, target, groupIndex, group, false));
                this.groups.push(group);
                state.data.rows.push(row);
            }

            this.setGroupIndex(target);
            this.refreshGroupTitle(target, groupIndex);
            this.resizeGroup(target);

            function _moveTr(index, frozen) {
                var serno = frozen ? 1 : 2;
                var prevTr = opts.finder.getTr(target, index - 1, 'body', serno);
                var tr = opts.finder.getTr(target, index, 'body', serno);
                tr.insertAfter(prevTr);
            }
        },

        updateRow: function (target, index, row) {
            var opts = $.data(target, 'datagrid').options;
            $.fn.datagrid.defaults.view.updateRow.call(this, target, index, row);
            var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
            var groupIndex = parseInt(tb.prev().attr('group-index'));
            this.refreshGroupTitle(target, groupIndex);
        },

        deleteRow: function (target, index) {
            var state = $.data(target, 'datagrid');
            var opts = state.options;
            var dc = state.dc;
            var body = dc.body1.add(dc.body2);

            var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
            var groupIndex = parseInt(tb.prev().attr('group-index'));

            $.fn.datagrid.defaults.view.deleteRow.call(this, target, index);

            var group = this.groups[groupIndex];
            if (group.rows.length > 1) {
                group.rows.splice(index - group.startIndex, 1);
                this.refreshGroupTitle(target, groupIndex);
            } else {
                body.children('div.datagrid-group[group-index=' + groupIndex + ']').remove();
                for (var i = groupIndex + 1; i < this.groups.length; i++) {
                    body.children('div.datagrid-group[group-index=' + i + ']').attr('group-index', i - 1);
                }
                this.groups.splice(groupIndex, 1);
            }

            this.setGroupIndex(target);
        },

        setGroupIndex: function (target) {
            var index = 0;
            for (var i = 0; i < this.groups.length; i++) {
                var group = this.groups[i];
                group.startIndex = index;
                index += group.rows.length;
            }
        }
    });


    // end of group view definition

    $.fn.propertygrid.defaults = $.extend({}, $.fn.datagrid.defaults, {
        groupHeight: 28,
        expanderWidth: 20,
        singleSelect: true,
        remoteSort: false,
        fitColumns: true,
        loadMsg: '',
        frozenColumns: [[
            {field: 'f', width: 20, resizable: false}
        ]],
        columns: [[
            {field: 'name', title: 'Name', width: 100, sortable: true},
            {field: 'value', title: 'Value', width: 100, resizable: false}
        ]],

        showGroup: false,
        groupView: groupview,
        groupField: 'group',
        groupStyler: function (value, rows) {
            return ''
        },
        groupFormatter: function (fvalue, rows) {
            return fvalue
        }
    });
})(jQuery);
